package com.fc.redap.shiro.listener;

import org.apache.shiro.cache.Cache;
import org.apache.shiro.cache.CacheManager;
import org.apache.shiro.session.Session;
import org.apache.shiro.session.SessionListener;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.Serializable;
import java.util.Deque;

public class KickOutSessionListener implements SessionListener {

    private static final Logger log = LoggerFactory.getLogger(KickOutSessionListener.class);

    private String cacheName = "kickout_cache";

    private CacheManager cacheManager;

    private Cache<String, Deque<Serializable>> cache;

    @Override
    public void onStart(Session session) {
        log.info("session created");
    }

    @Override
    public void onStop(Session session) {
        removeSessionFromCache(session);
    }

    @Override
    public void onExpiration(Session session) {
        removeSessionFromCache(session);
    }

    private void removeSessionFromCache(Session session) {
        String username = (String)(session.getAttribute("username"));
        if (username != null) {
            log.debug("remove session: " + session.getId() + " in deque of " + username
                    + "@kickOutSessionCache");
            Cache<String, Deque<Serializable>> cache = getCache();
            synchronized (cache) {
                Deque<Serializable> deque = cache.get(username);
                if (deque != null) {
                    deque.remove(session.getId());
                    if (deque.size() == 0) {
                        cache.remove(username);
                    }
                }
            }
        }
    }

    private Cache<String, Deque<Serializable>> getCache() {
        if (this.cache != null) {
            return this.cache;
        }
        return cacheManager.getCache(cacheName);
    }

    public void setCacheManager(CacheManager cacheManager) {
        this.cacheManager = cacheManager;
    }
}
